package org.fig.dependency.lookup;

import org.fig.ioc.overview.domain.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;



/**
 * @Description: 类型安全 依赖查找实例
 * @Author: Flynn Vanderboom
 * @Data: 2021/6/17 21:36
 */
@Configuration
public class TypeSafetyDependencyLookupDemo {
    public static void main(String[] args) {
        //创建BeanFactory容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

        //将当前类  ObjectProviderDemo 作为配置类 (Configuration Class)
        applicationContext.register(TypeSafetyDependencyLookupDemo.class);

        //启动应用上下文
        applicationContext.refresh();

        //演示 getBean 的安全性
        displayBeanFactoryGetBean(applicationContext);

        displayObjectFactoryGetBean(applicationContext);

        displayObjectProviderIfAvailable(applicationContext);


        displayListableBeanFactoryGetBean(applicationContext);

        displayObjectProviderStreamOps(applicationContext);

        applicationContext.close();
    }


    private static void displayObjectProviderIfAvailable(AnnotationConfigApplicationContext applicationContext){
        ObjectProvider<User> objectProvider = applicationContext.getBeanProvider(User.class);
        printBeansException("displayObjectProviderIfAvailable",()->{
            objectProvider.getIfAvailable();
        });
    }


    private static void displayObjectFactoryGetBean(AnnotationConfigApplicationContext applicationContext) {
        ObjectFactory<User> objectFactory = applicationContext.getBeanProvider(User.class);
        printBeansException("displayObjectFactoryGetBean",()->{
            objectFactory.getObject();
        });
    }

    public static void displayBeanFactoryGetBean(BeanFactory beanFactory) {
        printBeansException("displayBeanFactoryGetBean",()->{
            beanFactory.getBean(User.class);
        });
    }

    public static void displayListableBeanFactoryGetBean(ListableBeanFactory listableBeanFactory) {
        printBeansException("displayListableBeanFactoryGetBean",()->{
            listableBeanFactory.getBeansOfType(User.class);
        });

    }

    private static void displayObjectProviderStreamOps(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<User> objectProvider = applicationContext.getBeanProvider(User.class);
        printBeansException("displayObjectProviderStreamOps",()->{
            objectProvider.forEach(System.out::println);
        });
    }


        private static void printBeansException(String message,Runnable runnable){
        System.err.println("Source from : "+message);
        System.err.println("=================================");
        try{
            runnable.run();
        }catch (BeansException exception) {
            //--？生产环境不要用，会发生阻塞   该方法线程安全
            exception.printStackTrace();
        }
    }
}
